#include "../include/IDefaultEntityBehaviour.h"

//**************************
//Description : Constructor
//Parameters : Value for m_iX, m_iY,
//              m_iSpeedX, m_iSpeedY,
//              m_iWidth, m_iHeight
//              the ratio for the collision box
//              and the type of collision
//Note : None
//**************************
IDefaultEntityBehaviour::IDefaultEntityBehaviour(int _iX, int _iY,
                                                int _iSpeedX, int _iSpeedY,
                                                int _iWidth, int _iHeight,
                                                float _fRatioW, float _fRatioH,
                                                TYPE_COLLISION _iTypeCollision)
    : m_iX(_iX),
    m_iY(_iY),
    m_iSpeedX(_iSpeedX),
    m_iSpeedY(_iSpeedY),
    m_iWidth(_iWidth),
    m_iHeight(_iHeight),
    m_fCollisionBoxRatioWidth(_fRatioW),
    m_fCollisionBoxRatioHeight(_fRatioH),
    m_iTypeCollision(_iTypeCollision)
{
}

//**************************
//Description : Copy Constructor
//Parameters : A IDefaultEntityBehaviour
//Note : None
//**************************
IDefaultEntityBehaviour::IDefaultEntityBehaviour(IDefaultEntityBehaviour & _DefaultEntityBehaviour)
    : m_iX(_DefaultEntityBehaviour.m_iX),
    m_iY(_DefaultEntityBehaviour.m_iY),
    m_iSpeedX(_DefaultEntityBehaviour.m_iSpeedX),
    m_iSpeedY(_DefaultEntityBehaviour.m_iSpeedY),
    m_iWidth(_DefaultEntityBehaviour.m_iWidth),
    m_iHeight(_DefaultEntityBehaviour.m_iHeight),
    m_fCollisionBoxRatioWidth(_DefaultEntityBehaviour.m_fCollisionBoxRatioWidth),
    m_fCollisionBoxRatioHeight(_DefaultEntityBehaviour.m_fCollisionBoxRatioHeight),
    m_iTypeCollision(_DefaultEntityBehaviour.m_iTypeCollision)
{
}

//**************************
//Description : Destructor
//Parameters : None
//Note : None
//**************************
IDefaultEntityBehaviour::~IDefaultEntityBehaviour()
{
}

//**************************
//Description : Test if the entity is in collision with _Entity
//Parameters : None
//Return Value : true if there is collision, otherwise false
//Note : None
//**************************
bool IDefaultEntityBehaviour::CollideWith(IDefaultEntityBehaviour * _Entity) const
{
    if ( _Entity != NULL && m_iTypeCollision == _Entity->m_iTypeCollision)
    {
        // This is our width :
        //  [*********************]
        // With a ratio of 20 %
        //  [--------*****--------]
        //             ^
        //            m_iX
        // The x position of the left side is equal to m_iX - (width / 2)
        // The x position of the right side is equal to m_iX + (width / 2)
        // The x position of the left side with a ratio is equal to m_iX - (width*ratio / 2)
        // The x position of the right side is equal to m_iX + (width*ratio / 2)
        // The ratio width is at
        // Same for the height

        int iHalfCollisionBoxWidth_This = (int)(m_iWidth * m_fCollisionBoxRatioWidth / 2.0f);
        int iHalfCollisionBoxHeight_This = (int)(m_iHeight * m_fCollisionBoxRatioHeight / 2.0f);

        int iHalfCollisionBoxWidth_Entity = (int)(_Entity->m_iWidth * _Entity->m_fCollisionBoxRatioWidth / 2.0f);
        int iHalfCollisionBoxHeight_Entity = (int)(_Entity->m_iHeight * _Entity->m_fCollisionBoxRatioHeight / 2.0f);

        int TopThis = (int)( m_iY - iHalfCollisionBoxHeight_This );
        int TopEntity = (int)( _Entity->m_iY - iHalfCollisionBoxHeight_Entity );

        int BottomThis = (int)( m_iY + iHalfCollisionBoxHeight_This );
        int BottomEntity = (int)( _Entity->m_iY + iHalfCollisionBoxHeight_Entity );

        int LeftThis = (int)( m_iX - iHalfCollisionBoxWidth_This );
        int LeftEntity = (int)( _Entity->m_iX - iHalfCollisionBoxWidth_Entity );

        int RightThis = (int)( m_iX + iHalfCollisionBoxWidth_This );
        int RightEntity = (int)( _Entity->m_iX + iHalfCollisionBoxWidth_Entity );

        if (BottomThis < TopEntity)
            return false;
        if (TopThis > BottomEntity)
            return false;
        if (RightThis < LeftEntity)
            return false;
        if (LeftThis > RightEntity)
            return false;

        return true;
    }
    else
        return false;
}

//**************************
//Description : Return the type of collision of the entity
//Parameters : None
//Return Value : The type of collision
//Note : None
//**************************
int IDefaultEntityBehaviour::GetTypeCollision() const
{
    return m_iTypeCollision;
}

//**************************
//Description : Return the abscissa position of the entity
//Parameters : None
//Return Value : the abscissa position
//Note : None
//**************************
int IDefaultEntityBehaviour::GetX() const
{
    return m_iX;
}

//**************************
//Description : Return the ordinary position of the entity
//Parameters : None
//Return Value : the ordinary position
//Note : None
//**************************
int IDefaultEntityBehaviour::GetY() const
{
    return m_iY;
}



//**************************
//Description : Return the position of the entity
//Parameters : References on the abscissa and the ordinary position
//Return Value : None
//Note : None
//**************************
void IDefaultEntityBehaviour::GetPosition(int & _iX, int & _iY) const
{
    _iX = m_iX;
    _iY = m_iY;
}

//**************************
//Description : Set, if possible, the position of the entity on the abscissa
//Parameters : New values of m_iX
//Return Value : None
//Note : None
//**************************
void IDefaultEntityBehaviour::SetX(int _iX)
{
    m_iX = _iX;
}

//**************************
//Description : Set, if possible, the position of the entity on the ordinary
//Parameters : New values of m_iY
//Return Value : None
//Note : None
//**************************
void IDefaultEntityBehaviour::SetY(int _iY)
{
    m_iY = _iY;
}

//**************************
//Description : Add, if possible, a value on the abscissa
//Parameters : Add value for m_iX
//Return Value : None
//Note : None
//**************************
void IDefaultEntityBehaviour::AddX(int _iValue)
{
    m_iX += _iValue;
}

//**************************
//Description : Add, if possible, the position of the entity on the ordinary
//Parameters : Add value for m_iY
//Return Value : None
//Note : None
//**************************
void IDefaultEntityBehaviour::AddY(int _iValue)
{
    m_iY += _iValue;
}

//**************************
//Description : Set, if possible, the position of the entity
//Parameters : New values of m_iX and m_iY
//Return Value : None
//Note : None
//**************************
void IDefaultEntityBehaviour::SetPosition(int _iX, int _iY)
{
    m_iX = _iX;
    m_iY = _iY;
}

//**************************
//Description : Set the width of the entity
//Parameters : The new width
//Return Value : None
//Note : None
//**************************
void IDefaultEntityBehaviour::SetWidth(int _iNewWidth)
{
    m_iWidth = _iNewWidth;
}

//**************************
//Description : set the height of the entity
//Parameters : The new height
//Return Value : None
//Note : None
//**************************
void IDefaultEntityBehaviour::SetHeight(int _iNewHeight)
{
    m_iHeight = _iNewHeight;
}

//**************************
//Description : Return the width of the entity
//Parameters : None
//Return Value : the width
//Note : None
//**************************
int IDefaultEntityBehaviour::GetWidth() const
{
    return m_iWidth;
}

//**************************
//Description : Return the height of the entity
//Parameters : None
//Return Value : the height
//Note : None
//**************************
int IDefaultEntityBehaviour::GetHeight() const
{
    return m_iHeight;
}

//**************************
//Description : Return the ratio width of the entity
//Parameters : None
//Return Value : the ratio width
//Note : None
//**************************
float IDefaultEntityBehaviour::GetRatioWidth() const
{
    return m_fCollisionBoxRatioWidth;
}

//**************************
//Description : Return the ratio height of the entity
//Parameters : None
//Return Value : the ratio height
//Note : None
//**************************
float IDefaultEntityBehaviour::GetRatioHeight() const
{
    return m_fCollisionBoxRatioHeight;
}

//**************************
//Description : Return the speed on the abscissa of the entity
//Parameters : None
//Return Value : the aspeed on the abscissa position
//Note : None
//**************************
int IDefaultEntityBehaviour::GetSpeedX() const
{
    return m_iSpeedX;
}

//**************************
//Description : Return the speed on the ordinary of the entity
//Parameters : None
//Return Value : the aspeed on the ordinary position
//Note : None
//**************************
int IDefaultEntityBehaviour::GetSpeedY() const
{
    return m_iSpeedY;
}

//**************************
//Description : Return the speed of the entity
//Parameters : References on the speed of the abscissa and the ordinary
//Return Value : None
//Note : None
//**************************
void IDefaultEntityBehaviour::GetSpeed(int & _iSpeedX, int & _iSpeedY) const
{
    _iSpeedX = m_iSpeedX;
    _iSpeedY = m_iSpeedY;
}

//**************************
//Description :Set the speed of the entity on the abscissa
//Parameters : New values of m_iSpeedX
//Return Value : None
//Note : None
//**************************
void IDefaultEntityBehaviour::SetSpeedX(int _iSpeedX)
{
    m_iSpeedX = _iSpeedX;
}

//**************************
//Description :Set the speed of the entity on the abscissa
//Parameters : New values of m_iSpeedX
//Return Value : None
//Note : None
//**************************
void IDefaultEntityBehaviour::SetSpeedY(int _iSpeedY)
{
    m_iSpeedY = _iSpeedY;
}

//**************************
//Description : Update, if possible, the speed of the entity
//Parameters : New values of m_iSpeedX and m_iSpeedY
//Return Value : None
//Note : None
//**************************
void IDefaultEntityBehaviour::SetSpeed(int _iSpeedX, int _iSpeedY)
{
    m_iSpeedX = _iSpeedX;
    m_iSpeedY = _iSpeedY;
}

//**************************
//Description : Return wheter the entity is out of the screen or not
//Parameters : None
//Return Value : True if the entity is out of the screen, otherwise false
//Note : We return true if the entity is COMPLETELY out of the screen, not partially
//**************************
bool IDefaultEntityBehaviour::IsOutOfScreen() const
{
    if ( (m_iX + m_iWidth / 2) < GAME_WINDOW_X )
        return true;

    if ( (m_iX - m_iWidth / 2) >= (GAME_WINDOW_X + GAME_WINDOW_WIDTH) )
        return true;

    if ( (m_iY + m_iHeight / 2) < 0 )
        return true;

    if ( (m_iY - m_iHeight / 2) >= GAME_WINDOW_HEIGHT )
        return true;

    return false;
}

//**************************
//Description : Return wheter the entity is in the screen or not
//Parameters : None
//Return Value : True if the entity is in the the screen, otherwise false
//Note : We return true if the entity is COMPLETELY in the screen, not partially
//**************************
bool IDefaultEntityBehaviour::IsInTheScreen() const
{
    if ( (m_iX - m_iWidth / 2) < GAME_WINDOW_X )
        return false;

    if ( (m_iX - 1 + m_iWidth / 2) >= (GAME_WINDOW_X + GAME_WINDOW_WIDTH) )
        return false;

    if ( (m_iY - m_iHeight / 2) < 0 )
        return false;

    if ( (m_iY - 1 + m_iHeight / 2) >= GAME_WINDOW_HEIGHT )
        return false;

    return true;
}

//**************************
//Description : Return wheter the entity is out of the screen or not
//Parameters : A pointer on an IDefaultEntityBehaviour
//Return Value : True if the entity is out of the screen, otherwise false
//Note : Static function because we use it as a predicate
//**************************
bool IDefaultEntityBehaviour::EntityOutOfScreen(IDefaultEntityBehaviour * _entity)
{
    return _entity->IsOutOfScreen();
}

